package com.lagou.config;

import com.lagou.filter.ValidateCodeFilter;
import com.lagou.service.impl.MyAuthenticationServiceImpl;
import com.lagou.service.impl.MyUserDetailServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import javax.sql.DataSource;

/**
 * @author junbao
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    MyUserDetailServiceImpl myUserDetailService;

    @Autowired
    MyAuthenticationServiceImpl myAuthenticationService;

    @Autowired
    ValidateCodeFilter validateCodeFilter;

    /**
     * 身份安全管理器
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
        auth.userDetailsService(myUserDetailService);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        // 忽略静态资源
        web.ignoring().antMatchers("/css/**","/images/**","/js/**","/code/**");
    }

    /**
     * http请求方法
     * */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 开启httpBasic认证  --- 所有请求都需要认证访问
        // http.httpBasic().and().authorizeRequests().anyRequest().authenticated();

        http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class);

        // 开启表单认证 --- 放行登陆页面
        http.formLogin()
                .loginPage("/toLoginPage")
                .loginProcessingUrl("/login")
                .usernameParameter("username1")
                .passwordParameter("password1")
                .successForwardUrl("/")
                .successHandler(myAuthenticationService)
                .failureHandler(myAuthenticationService)
                .and().logout().logoutUrl("/logout")
                .logoutSuccessHandler(myAuthenticationService)
                .and().rememberMe()
                .tokenValiditySeconds(30)
                .rememberMeParameter("remember-me")
                .tokenRepository(getPersistentTokenRepository())
                .and().authorizeRequests().antMatchers("/toLoginPage").permitAll()
                .anyRequest().authenticated();

        // 关闭csrf（跨站请求）保护
        // http.csrf().disable();
        //开启csrf防护, 可以设置哪些不需要防护
        http.csrf().ignoringAntMatchers("/user/saveOrUpdate");

        // 加载同源域名下iframe页面
        http.headers().frameOptions().sameOrigin();

//        http.sessionManagement()
//                .invalidSessionUrl("/toLoginPage")
//                .maximumSessions(1)
//                .maxSessionsPreventsLogin(true); // 如果达到最大登陆数量就阻止登陆
//                // .expiredUrl("toLoginPage");

        // 开启跨域
        http.cors().configurationSource(corsConfigurationSource());
    }

    public static void main(String[] args) {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String encode = bCryptPasswordEncoder.encode("123456");
        System.out.println(encode);
        String encode1 = bCryptPasswordEncoder.encode("123456");
        System.out.println(encode1);
    }


    @Autowired
    DataSource dataSource;

    /**
     * token: 随机生成策略,每次访问都会重新生成
     * series: 登录序列号，随机生成策略。用户输入用户名和密码登录时，该值重新生成。使用remember-me功能，该值保持不变
     * expiryTime: token过期时间。
     * CookieValue=encode(series+token)
     * @return
     */
    @Bean
    public PersistentTokenRepository getPersistentTokenRepository() {
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        // 设置数据源
        tokenRepository.setDataSource(dataSource);
        // 启动时自动创建表
        // tokenRepository.setCreateTableOnStartup(true);
        return tokenRepository;
    }

    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        // 设置允许跨域的站点
        corsConfiguration.addAllowedOrigin("*");
        // 设置允许跨域的http方法
        corsConfiguration.addAllowedMethod("*");
        // 设置允许跨域的请求头
        corsConfiguration.addAllowedHeader("*");
        // 允许携带凭证
        corsConfiguration.setAllowCredentials(true);

        // 对所有的url生效
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        return source;
    }
}
